/*
 * Modelo0.cpp
 *
 *  Created on: 23/06/2012
 *      Author: natuchis
 */

#include "Modelo0.h"

typedef pair<char,Caracter> ParCaracter;

Modelo0::Modelo0() {

	this->mapaCarac = new map <char,Caracter*>;
	this->cantFrecuenciaTotal = 0;
}

Modelo0::~Modelo0() {

	for (this->itMapaCarac = this->mapaCarac->begin(); this->itMapaCarac != this->mapaCarac->end(); this->itMapaCarac++) {
		delete this->itMapaCarac->second;
	}

	delete this->mapaCarac;
}

void Modelo0::actualizar(string contexto, char carac) {

	if (existeCaracter(carac)) {
		this->mapaCarac->find(carac)->second->incrementarFrecuencia();
		this->cantFrecuenciaTotal++;
//		cout << "Incremente la frecuencia del caracter " << carac << " en el modelo0" << endl;
	}
	else {
//		cout << "Agregue el caracter " << carac << " en el modelo0" << endl;
		this->agregarCaracter(carac);
	}
}

void Modelo0::agregarCaracter(char carac) {

	this->mapaCarac->insert(pair<char,Caracter*>(carac, new Caracter()));
	this->cantFrecuenciaTotal++;
}

bool Modelo0::existeCaracter(char carac) {

	this->itMapaCarac = this->mapaCarac->find(carac);
	return (this->itMapaCarac != this->mapaCarac->end());
}

unsigned long int Modelo0::getFrecuenciaTotal(string contexto) {

	return this->cantFrecuenciaTotal;
}

void Modelo0::setExcluidos(string contexto, set<char> *excluidos) {

	for (this->itMapaCarac = this->mapaCarac->begin(); this->itMapaCarac != this->mapaCarac->end(); this->itMapaCarac++) {
		excluidos->insert(this->itMapaCarac->first);
	}
}

void Modelo0::comprimir(string contexto, char carac, set<char> *excluidos, Datos &datos, bool estoyEnElEof) {

	map<string, Caracter> mapa;

	unsigned long int frecEsc = this->getFrecuenciaEsc(contexto) - this->getCantExcluidosPresentesEnModelo(contexto,excluidos);
	mapa.insert(pair<string,Caracter>("ESC", Caracter(frecEsc)));
	this->agregarCaracteresNoExcluidos(mapa, excluidos);
	datos.setCaracteres(mapa);

	datos.setFrecTotal(this->getFrecuenciaTotal(contexto) - this->getFrecuenciaTotalExcluidos(contexto,excluidos) + frecEsc);

	if (!estoyEnElEof) {
		if (this->existeCaracter(carac)) {
			datos.setCaracAComp(string(1,carac));
		}
		else {
			datos.setCaracAComp("ESC");
		}
	}
	else {
		datos.setCaracAComp("ESC");
	}
}

unsigned long int Modelo0::getFrecuenciaTotalExcluidos(string contexto, set<char> *excluidos) {

	set<char>::iterator it;
	unsigned long int frecExcluidos = 0;

	for (it = excluidos->begin(); it != excluidos->end(); it++) {
		if (this->existeCaracter(*it)) {
			frecExcluidos += this->mapaCarac->find(*it)->second->getFrecuencia();
		}
	}
	return frecExcluidos;
}

void Modelo0::agregarCaracteresNoExcluidos(map<string, Caracter> &mapa, set<char> *excluidos) {

	for (this->itMapaCarac = this->mapaCarac->begin(); this->itMapaCarac != this->mapaCarac->end(); this->itMapaCarac++) {
		if (excluidos->find(this->itMapaCarac->first) == excluidos->end()) {
			mapa.insert(pair<string,Caracter>(string(1,this->itMapaCarac->first),*this->itMapaCarac->second));
		}
	}
}

unsigned long int Modelo0::getFrecuenciaEsc(string contexto) {

	unsigned long int frec;
	if (this->mapaCarac->empty()) {
		frec = 1;
	}
	else {
		frec = this->mapaCarac->size();
	}
	return frec;
}

void Modelo0::actualizarModeloYExcluidos(string contexto, char carac, set<char> *excluidos) {

	this->setExcluidos(contexto, excluidos);
	this->actualizar(contexto, carac);
}

bool Modelo0::existeCaracterEnEsteContexto(string contexto, char carac) {

	return this->existeCaracter(carac);
}

void Modelo0::agregarContexto(string contexto) {
}

void Modelo0::getMapa(string contexto, map<string,Caracter> &mapa, set<char> *excluidos) {

	unsigned long int frecEsc = this->getFrecuenciaEsc(contexto) - this->getCantExcluidosPresentesEnModelo(contexto,excluidos);
	mapa.insert(pair<string,Caracter> ("ESC",Caracter(frecEsc)));
	this->agregarCaracteresNoExcluidos(mapa,excluidos);
}

unsigned long int Modelo0::getCantExcluidosPresentesEnModelo(string contexto, set<char> *excluidos){

	set<char>::iterator it;
	unsigned long int frecExcluidos = 0;

	for (it = excluidos->begin(); it != excluidos->end(); it++) {
		if (this->existeCaracter(*it)) {
			frecExcluidos++;
		}
	}
	return frecExcluidos;
}
